﻿using System.Linq;
using Zeta.Game.Internals;

namespace KadalaSpree.XCore
{
    public class XElement : XObject
    {
        #region Fields

        private UIElement _element;
        private ulong _hash;
        private ElementName _name;

        public ulong Hash
        {
            get { return (_element != null) ? (ulong) GetProperty<ulong>(_element.Hash) : default(ulong); }
        }

        public bool HasText
        {
            get { return (_element != null) ? (bool) GetProperty<bool>(_element.HasText) : default(bool); }
        }

        public bool IsEnabled
        {
            get { return (_element != null) ? (bool) GetProperty<bool>(_element.IsEnabled) : default(bool); }
        }

        public bool IsVisible
        {
            get { return (_element != null) ? (bool) GetProperty<bool>(_element.IsVisible) : default(bool); }
        }

        public string Name
        {
            get { return (_element != null) ? (string) GetProperty<string>(_element.Name) : default(string); }
        }

        public string Text
        {
            get { return (_element != null) ? (string) GetProperty<string>(_element.Text) : default(string); }
        }

        public UIElement Element
        {
            get
            {
                if (!IsValid) Update();
                return (IsValid) ? _element : null;
            }
        }

        public ElementName ElementName
        {
            get
            {
                // Element name is unset and but we have a hash to lookup
                if (_name == ElementName.None && _hash != 0)
                {
                    _name = XLookup.Elements.ElementNameAndHash.FirstOrDefault(e => e.Value == _hash).Key;
                }
                return _name;
            }
        }

        public bool IsValid
        {
            get { return _element != null && _element.IsValid; }
        }

        public bool IsOpen
        {
            get
            {
                if (_element != null)
                {
                    //X.Logger.Log("XElement {4} IsOpen={0} IsEnabled={1} IsVisible={2} IsValid={3}", (_element.IsValid && _element.IsEnabled && _element.IsVisible), _element.IsEnabled, _element.IsVisible, _element.IsValid, _name);
                }
                return _element != null && _element.IsValid && _element.IsVisible;
            }
        }

        private object GetProperty<T> (object prop)
        {
            if (!IsValid) Update();
            return (IsValid) ? prop : default(T);
        }

        public void Click()
        {
            if (!IsValid) Update();
            _element.Click();
        }

        //public static IEnumerable<UIElement> UIMap { get; set; }
        //public bool Click();
        //public static UIElement FromHash(ulong hash);
        //public static UIElement FromName(string name);
        //public static IEnumerable<UIElement> GetChildren(UIElement parent);
        //public static bool IsValidElement(ulong hash);
        //public void SetText(string text);

        #endregion

        #region Constructors

        public XElement() {}

        public XElement (ulong hash)
        {
            
            _hash = hash;
            _element = UIElement.FromHash(hash);
            X.Logger.Instance.Log("Creating new XElement '{0}' from hash {1} found={2}", ElementName, hash, IsValid);
        }

        public XElement (UIElement element)
        {
            _element = element;
            _hash = _element.Hash;
        }

        #endregion

        #region Methods

        internal void Update()
        {
            if (_hash == 0)
            {
                X.Logger.Instance.Log("Unable to find element with hash {0}", _hash);
            }

            _element = UIElement.FromHash(_hash);

            if (!IsValid)
            {
                X.Logger.Instance.Log("Unable to find element with hash {0}", _hash);
            }                  
        }

        #endregion

        public override XObjectType XObjectType
        {
            get { return XObjectType.XElement; }
        }
    }
}